/**
 * 
 */
package com.app.utils.base.http;

import com.app.utils.spring.config.SystemError;

import java.math.BigInteger;

/**
 * 方案二：10进制和32进制相互转换
 * 
 * @author qiuxiaoj@163.com
 * @date 2020年3月19日
 *
 */
public class RadixConvert2 {
	private final static String DICTS = "0123456789ABCDEFGHJKLMNPRSTUWXYZ";
	private final static int MAX_RADIX = DICTS.length();

	/**
	 * 10进制转32进制
	 * 
	 * @param num
	 * @return
	 */
	public static String from10To32(BigInteger num) {
		return numericToString(num, MAX_RADIX);
	}

	/**
	 * 32进制转10进制
	 * 
	 * @param num
	 * @return
	 */
	public static BigInteger from32To10(String num) {
		return stringToNumeric(num, MAX_RADIX);
	}

	/**
	 * 10进制转N进制
	 * 
	 * @param radix:进制
	 * @return
	 */
	private static String numericToString(BigInteger num, int radix) {
		if (BigInteger.ZERO.compareTo(num) > 0 || radix < 2 || radix > MAX_RADIX) {
			/** 不支持负数或相应进制转换 */
			SystemError.wrapBs("6000", "邀请码异常");
		}
		StringBuilder sb = new StringBuilder();
		BigInteger radixBi = BigInteger.valueOf(radix);
		while (BigInteger.ZERO.compareTo(num) < 0) {
			sb.append(DICTS.charAt(num.mod(radixBi).intValue()));
			num = num.divide(radixBi);
		}
		return sb.reverse().toString();
	}

	/**
	 * N进制转10进制
	 * 
	 * @param s
	 * @param radix:进制
	 * @return
	 */
	private static BigInteger stringToNumeric(String s, int radix) {
		if (radix < 2 || radix > MAX_RADIX) {
			/** 进制小于2，或者大于最大进制 */
			SystemError.wrapBs("6000", "邀请码异常");
		}

		BigInteger num = BigInteger.ZERO;
		int sLen = s.length();
		int dictLen = MAX_RADIX;
		BigInteger bRadix = BigInteger.valueOf(radix);
		for (int i = 0; i < sLen; i++) {
			for (int j = 0; j < dictLen; j++) {
				if (DICTS.charAt(j) == s.charAt(i)) {
					num = num.add(bRadix.pow(sLen - i - 1).multiply(BigInteger.valueOf(j)));
					break;
				}
			}
		}
		if (BigInteger.ZERO.compareTo(num) > 0) {
			/** 转换后数值小于0 */
			SystemError.wrapBs("6000", "邀请码异常");
		}
		return num;
	}

	public static void main(String[] args) {
		BigInteger num = BigInteger.valueOf(Long.MAX_VALUE);
		System.err.println(num);
		System.err.println(from10To32(num));
		System.err.println(from32To10(from10To32(num)));
		System.err.println(from32To10("2ph9"));
	}

}
